
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <Inklude/Inklude.h>
#include <Inklude/ikCString.h>
#include <Inklude/ikCSharedMemory.h>

using namespace std;
using namespace Inklude;

ikCSharedMemory::ikCSharedMemory()
{
    m_hMemory = NULL;
    m_pBuffer = NULL;
}

ikCSharedMemory::~ikCSharedMemory()
{
	if (NULL != m_hMemory)
	{
		CloseHandle(m_hMemory);
        CloseHandle(m_hMutex);
		//DeleteCriticalSection(&m_csObj);
	}
    //SAFE_DELETE(m_buffer);
}

bool ikCSharedMemory::CreateMemory(Inklude::ikCString& SharedMemoryIdentifier, unsigned int MemorySize)
{
    m_hMemory = CreateFileMapping (INVALID_HANDLE_VALUE,
                                   NULL,
                                   PAGE_READWRITE,
                                   0,
                                   MemorySize,
                                   SharedMemoryIdentifier.c_tstr());
    if (NULL == m_hMemory)
    {
        cout << "Could not find shared memory" << endl;
        return false;
    }

    // I can't figure out why I use +1 in previous codes....
    m_pBuffer = reinterpret_cast<char*>(MapViewOfFile(m_hMemory, FILE_MAP_ALL_ACCESS, 0, 0, MemorySize));
    //m_pBuffer = reinterpret_cast<char*>(MapViewOfFile(m_hMemory, FILE_MAP_ALL_ACCESS, 0, 0, MemorySize + 1));

    if (NULL == m_pBuffer)
    {
        cout << "Could not map file" << endl;
        m_hMemory = NULL;
        return false;
    }
    m_bufSize = MemorySize;

    TCHAR tMutexName[256];
    _stprintf(tMutexName, TEXT("%s__%s"), TEXT("inklude_mutex_name"), SharedMemoryIdentifier.c_tstr());
    m_hMutex = CreateMutex(NULL, FALSE, tMutexName);
    DWORD err = GetLastError();
    return true;
}

bool ikCSharedMemory::ReadMemory (char* Buffer, unsigned int ReadSize, unsigned int Offset)
{
    char* tmpBuf = m_pBuffer + Offset + 1;
	bool _bResult = false;
    DWORD dwWaitResult = WaitForSingleObject(m_hMutex, 1000);
    if (WAIT_OBJECT_0 == dwWaitResult)
    {
        _bResult = (0 == memcpy_s(Buffer, m_bufSize-Offset, tmpBuf, ReadSize));
        m_pBuffer[0] = 0;
        ReleaseMutex(m_hMutex);
    }
    return _bResult;
}

bool ikCSharedMemory::WriteMemory(char* Buffer, unsigned int WriteSize, unsigned int Offset)
{
    char* tmpBuf = m_pBuffer + Offset + 1;
    bool _bResult = false;
    DWORD dwWaitResult = WaitForSingleObject(m_hMutex, 1000);
    if (WAIT_OBJECT_0 == dwWaitResult)
    {
        _bResult = (0 == memcpy_s(tmpBuf, m_bufSize-Offset, Buffer, WriteSize));
        m_pBuffer[0] = 1;
        ReleaseMutex(m_hMutex);
    }
    return _bResult;
}

bool ikCSharedMemory::IsNewlyWritten()
{
    bool _bResult = false;
    DWORD dwWaitResult = WaitForSingleObject(m_hMutex, 1000);
    if (WAIT_OBJECT_0 == dwWaitResult)
    {
        _bResult = (1 == m_pBuffer[0]);
        ReleaseMutex(m_hMutex);
    }

    return _bResult;
}

